laoban-dev.github.io

Adding loaban to an existing code base

The purpose of this little training exercise is to go through the process of adding laoban to an existing project

Source

All the source code is here.

If you clone it with git clone https://github.com/laoban-training/convertexistingproject.git you will get the ‘ starting state’

Exploring the project

The project is a simple typescript monorepo project. It has a main package that uses three libraries lib1,lib2 and lib3. These packages are located under ‘modules’ in the root of the project.

     lib1      lib3
       \       /
        lib2  /
          \  /
           main    

Each library for this very simple example just export a string that is displayed by main

Setting up with yarn

Yarn is set up to use workspaces. For more info read here. In my view it is very hard to work with a javascript/typescript monorepo without workspaces.

cd <to the project root directory>
yarn

Compiling and running the project without laoban

This can be done with

cd modules/lib2
tsc --noEmit false --outDir dist
cd ../lib3
tsc --noEmit false --outDir dist
cd ../main
tsc --noEmit false --outDir dist
# and now we can run it with:
node dist/index.js

If we aren’t using a tool like laoban we need to write scripts for even the simplest of activities. For example when we compile we need to compile all the packages in the right order. This is done in the compile script in the root package.json file. The right order for compilation is that lib2 and lib3 can be compiled in parallel but main needs to be compiled after lib2 and lib3 are compiled.

Note that the scripts PROBABLY DON’T WORK ON YOUR MACHINE. Do you use Bash or Zsh or Windows CMD or Powershell or something else provided by your IDE? It’s also the case that usually in projects I have seen that scripts used in the CI/CD pipeline are different to the scripts that run on the developer’s machine.

Note also that we need another script for everything we want to do: test, compile, coverage analysis, integration tests, performance testing…everything. And each time the project structure changes we need to maintain these scripts.

Compiling the project with laoban

If we had laoban installed we could use laoban compile. Laoban will do the parallelism and the correct order. We can’t do that until we have installed laoban and configured the project.

Setting up the project with laoban

If we are going to use the ‘default templates’ then this is very easy. The default templates are for a very precise version of typescript (4.0.5). It is very easy to make a template for a different version of typescript and we explore that below

npm i -g laoban

and check it works with

laoban --version

If you have problems read Installing laoban

Check for impact

When the default templates are used there may be a change to package dependencies. It is important to understand what will happen when we do this

laoban admin analyze --showimpact

This produces the following

{
  "modules/lib1": {},
  "modules/lib2": {
    "devDependencies": {"typescript": "^4.9.4 => ^4.0.5"}
  },
  "modules/lib3": {
    "devDependencies": {"typescript": "^4.9.3 => ^4.0.5"}
  },
  "modules/main": {
    "devDependencies": {"typescript": "^4.9.4 => ^4.0.5"}
  }
}

This tells us that using the default templates will downgrade the version of typescript. Obviously we don’t want to do this! We’ll see how to solve this below.

Generate the laoban files

Laoban needs to have a laoban.json file in the root of the project, and a project.details.json file in each package. We could add them manually (which is error prone) or we can use the laoban admin init command to do it for us. If we want to we can see ‘what it would do’ with the --dryrun option


```shell
laoban admin init --dryrun

In your IDE look at what this has done. There are now some new files. These don’t work: they are ‘test’ files and only exist for you to look at them and ‘be happy’ before actually doing the work

We can now run the command without the --dryrun option

laoban admin init

And we can get rid of the ‘test’ files now that laoban is configured using

laoban clean

Playing with the project and laoban

You can explore what this has done in an IDE. Observe that it hasn’t changed any of the package.json files yet. Also remember that we haven’t fixed the issue with typescript yet

You can see what packages exist, what template they are using and how they depend on each other with

laoban packages

You can compile them

laoban compile

You can test them with

laoban test

Fix the typescript version

We want to make a new template that is like the old template, but with a different typescript version. For this we need to select a directory that has package.json already set up the way we want. In this example we select modules/main. We can then run

laoban admin updatetemplate --directory modules/main

Go look at the files system: you will see that a new directory has been created under laoban/templates/typescript. In it there is a .template.json (a template definition) and a package.json (the template itself). These can be edited by hand, although it is rare to modify the .template.json file manually.

Note how small the package.json in the template is: it just holds the ‘differences’ between it and the parent:

{
  "devDependencies": {
    "typescript": "^4.9.4"
  }
}

Check for impact again

laoban admin analyze --showimpact

This still shows some impact, but this is acceptable. In the past we had forgotten to update the typescript version in lib3. This kind of error is common without tools like laoban

{
  "modules/lib1": {},
  "modules/lib2": {},
  "modules/lib3": {
    "devDependencies": {
      "typescript": "^4.9.3 => ^4.9.4"
    }
  },
  "modules/main": {}
}

laoban update

When we make changes to package.details.json we need to run laoban update to update the package.json files. What this command does is ‘make sure our project is in line with the template’. package.json is no longer the source of truth, it is a generated file from package.details.json and the selected template in it

laoban update

After doing this it is a good idea to look with git and see if any ‘damage’ has been done. Check the package.json files especially

Check everything still works

yarn                        # should report 'no change'
laoban compile
laoban status              

The last command will display

                   compile
modules/lib2       true
modules/lib3       true
modules/main       true

So far so good! Let’s continue

laoban test

But wait! The last two lines says

modules\lib1 has an error. To view log use
laoban log -p modules/lib1$

I usually run laoban status at times like this to see if there are other problems:

laoban status

which gives

                   compile test
modules/lib1               false
modules/lib2       true    true
modules/lib3       true    true
modules/main       true    true
exit code 1

How can we find out what is the matter in lib1? We can scroll in the console and look, but there is a better way. We can just cut and paste the recommended command (or if we are lazy we can type laoban log -p lib1 which works just as well because lib1 is unique)

laoban log -p modules/lib1$

We could also look in the .sessions directory. There is a directory for each script. The last one is the one we want. All of these show us:

$ jest --config jest.config.json
No tests found, exiting with code 1
Run with `--passWithNoTests` to exit with code 0

Basically lib1 has been written without any tests. We can fix this by adding a test to lib1 or by telling laoban to not run tests on lib1. We’ll do the latter. We can do this by editing the package.details.json file for lib1 and changing the test property to false. We can then run laoban test again. This time we see no errors

                   compile test
modules/lib1               false
modules/lib2       true    true
modules/lib3       true    true
modules/main       true    true
exit code 1

What! What’s going on? We’ve told laoban not to run tests on lib1 but it still says that lib1 has failed tests. The answer is that the status shows the last time tests were run and we no longer run tests in lib1. We can fix this by running laoban clean and then laoban test again. This time we see

                   test
modules/lib2       true
modules/lib3       true
modules/main       true

As you can see the laoban status command gives us a nice view of the ‘state’ of our project. It can be used in the CI/CD after a build to check that everything is ok. (it returns an exit code of 1 if there was a problem)

Summary

The actual things we have done are

git clone https://github.com/laoban-training/convertexistingproject.git
cd convertexistingproject
yarn
laoban admin init
laoban admin analyze --showimpact                            # showed us that we had a problem with the typescript version
laoban admin updatetemplate --directory modules/main         # fixed the typescript version
laoban update                                                # updated the package.json files, and any other files required by the template
laoban compile
laoban test
laoban status                                                # showed us that we had a problem with the tests in lib1
laoban log -p lib1
# edit package.details.json for lib1 to set test to false
laoban clean
laoban test
laoban status

The only ‘decision points’ were ‘what do we do about the downgraded typescript version’ and ‘how do we fix the tests in lib1

Finished

The project is now configured to use laoban. You can now use laoban to build, test and publish your project.