Skip to content

estimate output improvements#303

Open
rhansen wants to merge 7 commits intoDebian:masterfrom
rhansen:estimate-output
Open

estimate output improvements#303
rhansen wants to merge 7 commits intoDebian:masterfrom
rhansen:estimate-output

Conversation

@rhansen
Copy link
Contributor

@rhansen rhansen commented Feb 23, 2026

The significant changes in this PR:

  • Disable colorized output on non-terminals and avoid hard-coded colorization escape codes by using a terminal color module.
  • Don't re-render an already rendered dependency subtree. This eliminates some unnecessary noise, and it makes it possible to render dependency cycles (e.g., golang.org/x/net <-> golang.org/x/crypto).
  • List the Debian package name and version when printing "in NEW" lines.

There are also some related code cleanups.

(please do not squash the commits in this PR)

@n-peugnet
Copy link
Contributor

n-peugnet commented Feb 23, 2026

I didn't test this yet, but I am mostly OK with these changes, just a few comments:

  • Disable colorized output on non-terminals and avoid hard-coded colorization escape codes by using a terminal color module.

We usually try to avoid adding too much dependencies to dh-make-golang, especially to make it easier to backport. I didn't check these specific dependencies, they might be alright (stable and already in Debian), but if it is easy to write without adding dependencies it would be appreciated.

  • Don't re-render an already rendered dependency subtree. This eliminates some unnecessary noise, and it makes it possible to render dependency cycles (e.g., golang.org/x/net <-> golang.org/x/crypto).

Does this mean the repeated dependencies (with a number in parenthesis) are not displayed any more? I did add this on purpose, see the reasoning here: #241

  • List the Debian package name and version when printing "in NEW" lines.

Seems nice, I originally decided to simply put an hyperlink to reduce the clutter, but this might also look good.
BTW, the link URL might be outdated now that the DFSG-team has its own dashboard.

There are also some related code cleanups.

These also look nice

Copy link
Contributor

@ottok ottok left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good! We should however not merge this until the new dependency is packaged, or alternatively move that commit into a separate PR.

This improves readability, and makes it easier for a future commit to
change how the output is handled.  For example, the lines could be
written immediately to stdout instead of saved in a slice to reduce
memory usage for complex modules, or a 3rd party package could be used
to produce the terminal color codes.
Repeating the subtree has a few problems:
  * It adds a lot of unneeded noise to the output.
  * It makes it impossible to render dependency cycles, which Go
    permits (e.g., golang.org/x/net <-> golang.org/x/crypto).
  * It over-counts how much a dependency is needed.  For example, with
    the following dependencies:

        a -> b
        a -> c
        a -> d
        b -> c
        c -> d

    it used to print something like:

        a
          b
            c
              d
          c (2)
            d (2)
          d (3)

    and now it prints:

        a
          b
            c
              d
          c (2)
          d (2)

    Stated precisely, the number is now the number of edges in the
    dependency graph that point to the dependency, not the number of
    paths from the root node to the dependency.
Automatically disable escape codes when stdout is not a terminal for
the sake of tools that might parse this utility's output.  Add a new
command-line option to allow the user to force color on or off.
@rhansen
Copy link
Contributor Author

rhansen commented Feb 25, 2026

  • Disable colorized output on non-terminals and avoid hard-coded colorization escape codes by using a terminal color module.

We usually try to avoid adding too much dependencies to dh-make-golang, especially to make it easier to backport. I didn't check these specific dependencies, they might be alright (stable and already in Debian), but if it is easy to write without adding dependencies it would be appreciated.

I removed that dependency. I will open a separate PR to use github.com/fatih/color (packaged as golang-github-fatih-color-dev) once fatih/color#255 is merged and the Debian package is updated to include it.

  • Don't re-render an already rendered dependency subtree. This eliminates some unnecessary noise, and it makes it possible to render dependency cycles (e.g., golang.org/x/net <-> golang.org/x/crypto).

Does this mean the repeated dependencies (with a number in parenthesis) are not displayed any more? I did add this on purpose, see the reasoning here: #241

The number is still there, but it now counts something different: Instead of showing the number of paths from the root module (the root node of the dependency graph) to the dependency it now counts the number of edges pointing to the dependency (the number of times the dependency appears as a requirement in a go.mod). I think this is a more useful metric anyway. I updated the commit message to explain this.

  • List the Debian package name and version when printing "in NEW" lines.

Seems nice, I originally decided to simply put an hyperlink to reduce the clutter, but this might also look good. BTW, the link URL might be outdated now that the DFSG-team has its own dashboard.

I changed the URL to the DFSG team dashboard.

Thank you both for reviewing!

@n-peugnet
Copy link
Contributor

Does this mean the repeated dependencies (with a number in parenthesis) are not displayed any more? I did add this on purpose, see the reasoning here: #241

The number is still there, but it now counts something different: Instead of showing the number of paths from the root module (the root node of the dependency graph) to the dependency it now counts the number of edges pointing to the dependency (the number of times the dependency appears as a requirement in a go.mod). I think this is a more useful metric anyway. I updated the commit message to explain this.

I understand the reasoning, but there is an issue with this approach, it can miss some dependencies. Consider for example this estimate command: dh-make-golang estimate -git_revision v1.8.4 github.com/livekit/livekit-server

With your branch I get:
2026-02-25-131759_504x315_scrot

Whereas on master I get:
2026-02-25-131745_506x630_scrot

Note the "buf.build" dependencies especially that get cut out in your branch. This is because of Module graph pruning, which will remove a dependency from the graph if is is not directly used by the code that requires it.
This means it is possible that some instances of the missing modules produce a tree with more dependencies than the others, and this instance is not necessarily the first encountered.

I know that this is an "estimate" command anyway, but I for one would prefer that it show more redundant lines rather than make the work appear simpler than what it really is.

@rhansen
Copy link
Contributor Author

rhansen commented Feb 25, 2026

Note the "buf.build" dependencies especially that get cut out in your branch.

That's due to a bug in graph construction done by estimate. Note that github.com/livekit/protocol was visited earlier, but it's not the same node in the graph as the github.com/livekit/protocol node that is visited later. If it was the same node, the dependencies of github.com/livekit/protocol would have been printed the first time it was visited.

I would fix that bug (and others I've noticed) before merging this PR, but there's a chicken-and-egg problem: if I fix the graph construction bugs, dependency cycles become common (e.g., golang.org/x/net <-> golang.org/x/crypto). Without this PR, these dependency cycles cause estimate to go into an infinite loop and eventually OOM.

(BTW, I recently wrote gomoddepgraph to address the graph construction bugs in estimate, and would like to eventually switch to it after getting consensus on the mailing list.)

@n-peugnet
Copy link
Contributor

n-peugnet commented Feb 26, 2026

That's due to a bug in graph construction done by estimate. Note that github.com/livekit/protocol was visited earlier, but it's not the same node in the graph as the github.com/livekit/protocol node that is visited later. If it was the same node, the dependencies of github.com/livekit/protocol would have been printed the first time it was visited.

So, do you think it does not come from module graph pruning? I assumed it was because of this that multiple occurrences of the same modules could have a different list of dependencies.

I would fix that bug (and others I've noticed) before merging this PR, but there's a chicken-and-egg problem: if I fix the graph construction bugs, dependency cycles become common (e.g., golang.org/x/net <-> golang.org/x/crypto). Without this PR, these dependency cycles cause estimate to go into an infinite loop and eventually OOM.

What do you think about keeping only the refactoring and color related parts in this PR, and do another one that completely replaces the dependency graph part, and fixes the output accordingly?

(BTW, I recently wrote gomoddepgraph to address the graph construction bugs in estimate, and would like to eventually switch to it after getting consensus on the mailing list.)

I did read most of this package's documentation, it seems really nice! Do you plan on merging it inside dh-make-golang or keep it as a separate module?
Your plan would be to switch to the RequirementsComplete() function, parsing the go.mod files ourselves instead of relying on go mod graph right? This seems like a good idea and a more robust solution than what I quickly made to fix the estimate command when it was completely broken.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants