As I’ve been writing my first highly modularized Android app for the last 6 months, I had to constantly look at how the dependency graph (composed by the Gradle modules) was evolving. You usually may have an initial idea on how your graph should look like, but new ideas and unexpected issues arise, so it’s hard to always stick to the plan and it’s normal to move things around once in a while, especially in the beginning of the project. Being able to look at the current graph structure really helps making decisions and move forward.
In the very beginning I had drawings and pictures of drawings from previous discussions with colleagues to guide my design. As the graph was taking its own shape, I started using Jake Wharton's Gradle task to generate a visual representation of the graph so I could look at it from time to time. At some point I realized how valuable the information I was getting out of it was: it guided my decisions on how a new module could fit there, it helped me prevent circular dependencies, and it made me happy to see how the project was growing.
For the size of my project, I realized the graph would also be extremely helpful for someone getting onboarded in the codebase. So as I was randomly working in the README file one day, I thought to myself: "it would be cool to have the graph here, but it's a shame how it would get out of date super quickly". Until I gave it a bit more thought and the idea behind this blogpost was born.
Show me the code
- We need the
projectDependencyGraphGradle task, so the first step is to add it in our project and reference it in our root build file.
- There's a small change we need to make there, though: it originally creates the
rootProject.buildDir, which is usually ignored by our version control system. Instead, we can use
rootProject.rootDirand place the graph somewhere within our project.
- Then we need to define the GitHub action that will automatically generate, commit and push the graph. This is what the job looks like:
Thankfully there's a great GitHub action that sets up Graphviz for us, which is the tool used by the Gradle task to generate the graph. That's our second step there:
ts-graphviz/setup-graphviz@v1. Third step is then running the task to generate the graph.
Once we have the graph, we need to commit it. We simply run a few Git commands to setup the user that'll own the commit and for the commit itself. We want to make sure the command doesn't fail if there are no changes (maybe the graph hasn't changed since the last time it was updated), that's why the command looks odd. Don't ask me about it, I just copied from here 💁♂️
Lastly we have to push, and again there's an action for that. Even though our action is pushing to master, it won't trigger a new run even if the workflow is configured to be triggered by pushes to master, so there's no concern around being stuck in recursive runs.
Show me the graph
With the Gradle task and the GitHub action in place, we can now simply reference the graph PNG file like this in the README:
It'll depend on what output directory we chose, but that's pretty much it! ✨
It's great to see the magic happening:
If you see a way to improve this setup or have any idea on how to apply the general concept in another scenario, hit my up on Twitter!