Scale CI runs with Nx Affected Commands

Share this video with your friends

Send Tweet
Published 2 years ago
Updated 2 years ago

Nx particularly shines when it comes to scaling in a large repository, but it can even be beneficial for smaller workspaces. Continuous integration time is particularly interesting. There's nothing more annoying when you have to wait for that pipeline runs to finish so that you can finally merge your PR. This gets worse as your workspace grows and has more and more apps & libs. Nx comes with "affected commands" to help with that. In this lesson we're going to learn how we can leverage those to drastically reduce the time involved in compiling/testing/linting projects.

Instructor: [0:00] As you have seen, Nx comes with a variety of commands already preset for you like you have already build commands, serve commands, test and link commands, which you can all see in the workspace json, basically in that architect node.

[0:12] Obviously, running all of these commands, especially in CI like nx build store and nx build the different kind of libraries and API projects, that will be much work and will be hard to set up, because each time you add a new library or new project, you would have to configure all your build setup.

[0:31] There's a much bigger problem underlying this thing. As you can see, our Nx workspace, if we again use the dependency graph, has grown quite a bit. We have an intime test. We have to store API application here, and a series of different kind of libraries.

[0:48] This is quite a small workspace, because we use it just for learning purposes and obviously it's quite simple. In a real-world project setup, you can have hundreds of applications and hundreds of libraries here.

[1:01] This comes with scalability issues. We cannot run and build all of them and test all of them and Lint all of them every time a PR gets pushed up and run through CI, but obviously, you want to make sure that whenever you change something in your monorepo, that things still work.

[1:19] Nx can help you scale this. One way to do that is by a so-called nx affected commands. Assume, for instance, we change something in a store feature game detail library. In that case, basically, we could work up the dependency graph and exactly know which libraries we have to build again, test again, or also for our instance, run intime tests again.

[1:41] This could be achieved by the affected command. That simulates such a change. For instance, if we go into the store feature game detail component, let's add here some console.log statement. An affected command basically goes and uses your git history to analyze what changes have been made, and therefore to identify which projects of the dependency graph have to be retest and rebuilt.

[2:06] Each of these Nx affected commands has a base property which points to the actual base branch which you want to merge to. By default, this is the master branch. Or, you could also specify a different one if you go to the nx.json configuration file.

[2:21] In the affected section here, you can define your default base which could be main or something else that matches your company guidelines. [inaudible] this master, but since in this course I have a series of stacked branches where each branch depends on a previous branch, our base will be the 16 adjust jest tests from a previous lesson.

[2:44] Before we run one of the commands, we can do something like nx affected:dep-graph, use that base branch and show just the dependency graph with affect notes.

[2:57] What you see is exactly the scenario which we have set before. If we look again at the before graph, we imagine to having a change in the store feature game detail and therefore only having to change this branch up here, which is exactly what this visualization shows us.

[3:13] You can see the changes here so we have to build or test the store application and we also have to run the store end-to-end tests again because they might touch on some parts, which depend on that changes that have been made in the dependent feature game detail library.

[3:27] All of the auto projects such as the API project, the util interfaces, even the store util formatters, which is being used by both the store and the store feature game detail, don't have to be retested because they didn't change. There is no need to run through that process again.

[3:44] While this was the visualization of the actual affect, the dependency graph, we can use those affect commands for all the based targets which we have in here. If we go in our workspace json, we can run all of the affected tests. We just use the test target here, run again, and you can see now that we will run the test for store and store feature game detail.

[4:09] Similarly, we can also run all affected Lints. We just exchange here the target from test to linting and it will do the same job and just run a linting process on all of those projects.

[4:23] As you can imagine, this is really powerful especially in your CI configuration. For instance, to run all the test cases, you would just use the test target here on your CI configuration to run only those projects that have been touched by a given PR.

[4:38] Most often also that base here can be read from some environment variable that a CI pipeline gives you. This can be fully customized even in situations where you don't merge to the master branch, but you have some stack PRs that merge into each other.